import os

from django.conf import settings
from httprunner import loader, compat
from httprunner.cli import main_run
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.parsers import MultiPartParser
from rest_framework.response import Response
from rest_framework.views import APIView

from sqtp.models import Request, Config, Case, Step
from sqtp.serializers import RequestSerializer, ConfigSerializer, CaseSerializer, StepSerializer


class RequestViewSet(viewsets.ModelViewSet):
    queryset = Request.objects.all()
    serializer_class = RequestSerializer


class ConfigViewSet(viewsets.ModelViewSet):
    queryset = Config.objects.all()
    serializer_class = ConfigSerializer


'''
用户不会作为序列化参数入参的
'''


class CaseViewSet(viewsets.ModelViewSet):
    queryset = Case.objects.all()
    serializer_class = CaseSerializer
    '''
    在执行 POST 创建数据时额外传一个 created_by 字段的值,字段必须得有哈
    '''

    def perform_create(self, serializer):
        serializer.save(create_by=self.request.user)

    def perform_update(self, serializer):
        serializer.save(update_by=self.request.user)

    '''
    methods=['GET'] → 这个接口只接受 GET 请求
    detail=True → URL 会带主键（pk），作用对象是单个资源（比如单个 Case）
    url_path='run' → 在 URL 里显示成 /run
    url_name='run_case' → 反向解析 URL 时用的名字
    '''

    @action(methods=['GET'], detail=True, url_path='run', url_name='run_case')
    # 完整的url等于/cases/<int:case_id>/run
    def run_case(self, request, pk):
        # 获取序列化器
        case = Case.objects.get(pk=pk)  # 根据ID获取当前用例
        # 返回当前 ViewSet 的序列化器实例,instance=case 表示这是序列化“已有对象”的模式，而不是创建模式
        serializer = self.get_serializer(instance=case)
        path = serializer.to_json_file()
        '''
        运行用例文件
        Exit code 0
        All tests were collected and passed successfully
        所有测试均已收集并成功通过
        Exit code 1
        Tests were collected and run but some of the tests failed
        收集并运行了测试，但有些测试失败了
        Exit code 2
        Test execution was interrupted by the user
        测试执行被用户中断
        Exit code 3
        Internal error happened while executing tests
        执行测试时发生内部错误
        Exit code 4
        pytest command line usage error
        pytest 命令行使用错误
        Exit code 5
        No tests were collected
        未收集测试
        '''
        code = main_run([path])
        if code != 0:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'error': '运行失败，检查参数是否传入正确',
                    'retcode': code
                }
            )
        return Response(data={'msg': 'success', 'retcode': 200})


class StepViewSet(viewsets.ModelViewSet):
    queryset = Step.objects.all()
    serializer_class = StepSerializer


class FileUploadView(APIView):
    parser_classes = [MultiPartParser]

    def put(self, request, filename, format=None):
        # 接受文件
        upload_path = settings.UPLOAD_DIR
        os.makedirs(upload_path, exist_ok=True)

        file_obj = request.data.get('case_file')
        if not file_obj:
            raise ValidationError("未接收到文件")

        # 保存文件
        save_path = os.path.join(upload_path,filename)
        with open(save_path,'wb')as f:
            for chunk in file_obj.chunks():
                f.write(chunk)

        # 检查文件内容是否符合hr3格式
        try:
            content = loader.load_test_file(f'{upload_path}/{filename}')
            validate_case = compat.ensure_testcase_v4(content)
        except Exception as e:
            raise ValidationError(f"错误的httprun4格式:{repr(e)}")

        validate_case['project_id'] = 1
        serializer = CaseSerializer(data=validate_case)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
        return Response(status=200, data={'msg': 'upload success', 'retcode': 200})
